import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.List;


public class MyPerson implements Person {
	private Set<Person> children = new HashSet<Person>();
	private Set<Person> parents = new HashSet<Person>();
	private char gender = MALE;
	private String name ="";
	private Person spouse=null;
	private long ssn=0;
	
	public static char MALE='M';
	public static char FEMALE='F';
	
	public MyPerson(String name, long ssn, char gender) {
		setName(name);
		setSSN(ssn);
		setGender(gender);
	}
	
	@Override
	public void addChild(Person child) {
		if (child!=null && !children.contains(child)) {
			children.add(child);
			child.addParent(this);
		}
	}

	@Override
	public void addParent(Person parent) {
		if (parent!=null && ! parents.contains(parent)) {
			parents.add(parent);
			parent.addChild(this);
		}
	}

	@Override
	public Set getChildren() {
		return children;
	}

	@Override
	public char getGender() {
		return gender;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public Set getParents() {
		return parents;
	}

	@Override
	public Person getSpouse() {
		return spouse;
	}

	@Override
	public long getSSN() {
		return ssn;
	}

	@Override
	public boolean hasSpouse() {
		return (spouse!=null);
	}

	@Override
	public boolean isRelated(Person person) {
		//relate to self
		if (person==this) {
			return true;
		}
		else if (person==null) {
			return false;
		}
		//find if related to any know relative
		else {
			List<Person> relatives = getRelatives();
			return relatives.contains(person);
		}
	}
	
	private List<Person> getRelatives() {
		List<Person> relatives = new LinkedList<Person>();
		getRelativesHelper(relatives, this);
		return relatives;
	}
	
	private void getRelativesHelper(List<Person> relatives, Person person) {
		if (person==null) {
			return;
		}
		if (relatives.contains(person)){
			return;
		}
		relatives.add(person);
		getRelativesHelper(relatives, person.getChildren().toArray());
		getRelativesHelper(relatives, person.getParents().toArray());
		getRelativesHelper(relatives, person.getSpouse());

		relatives.addAll(person.getChildren());
		relatives.addAll(person.getParents());
		relatives.add(person.getSpouse());
	}
	
	private void getRelativesHelper(List<Person> relatives, Object[] people) {
		for (Object obj:people) {
			Person person=null;
			try {
				person = (Person)obj;
			} catch (Exception e) {
				continue;
			}
			if (person!=null) {
				getRelativesHelper(relatives, person);
			}
		}
	}
		
	@Override
	public void setGender(char gender) {
		this.gender=gender;
	}

	@Override
	public void setName(String name) {
		this.name=name;
	}

	@Override
	public void setSpouse(Person spouse) {
		if (getSpouse()==spouse) {
			return;
		}
		this.spouse = spouse;
		spouse.setSpouse(this);
		
	}

	@Override
	public void setSSN(long ssn) {
		this.ssn=ssn;
	}

	@Override
	public String toString() {
		return getName() + getSSN() + getGender();
	}
	
	

}
